home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
graphics
/
povray2.zip
/
SOURCE
/
EXPRESS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-08
|
13KB
|
553 lines
/****************************************************************************
* express.c
*
* This module implements an expression parser for the floats, vectors and
* colours in scene description files.
*
* from Persistence of Vision Raytracer
* Copyright 1993 Persistence of Vision Team
*---------------------------------------------------------------------------
* NOTICE: This source code file is provided so that users may experiment
* with enhancements to POV-Ray and to port the software to platforms other
* than those supported by the POV-Ray Team. There are strict rules under
* which you are permitted to use this file. The rules are in the file
* named POVLEGAL.DOC which should be distributed with this file. If
* POVLEGAL.DOC is not available or for more info please contact the POV-Ray
* Team Coordinator by leaving a message in CompuServe's Graphics Developer's
* Forum. The latest version of POV-Ray may be found there as well.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
*****************************************************************************/
#include "frame.h"
#include "vector.h"
#include "povproto.h"
#include "parse.h"
/* This file implements a simple recursive-descent parser for reading the
input file. */
extern DBL Max_Trace_Level;
extern char VerboseFormat;
extern unsigned int Options;
extern char Stat_File_Name[FILE_NAME_LENGTH];
extern struct Reserved_Word_Struct Reserved_Words [];
extern DBL Antialias_Threshold;
extern struct Token_Struct Token;
extern char String[MAX_STRING_INDEX];
extern COLOUR_MAP_ENTRY *Build_Entries;
extern FRAME Frame;
extern DBL Clock_Value;
extern char **Symbol_Table;
extern int Max_Intersections;
extern DBL Language_Version;
extern METHODS Csg_Height_Field_Methods;
static DBL Parse_Float_Factor PARAMS((void));
static DBL Parse_Float_Term PARAMS((void));
static void Parse_Vector_Factor PARAMS((VECTOR *Vector));
static void Parse_Vector_Term PARAMS((VECTOR *Vector));
extern struct Constant_Struct Constants[MAX_CONSTANTS];
extern int Number_Of_Constants;
extern int Previous;
extern short Have_Vector;
extern short Not_In_Default;
extern TOKEN *Brace_Stack;
extern int Brace_Index;
static DBL Parse_Float_Factor ()
{
DBL Local_Float;
EXPECT
CASE (FLOAT_TOKEN)
Local_Float = Token.Token_Float;
EXIT
END_CASE
CASE (FLOAT_ID_TOKEN)
Local_Float = *((DBL *) Token.Constant_Data);
EXIT
END_CASE
CASE (CLOCK_TOKEN)
Local_Float = Clock_Value;
EXIT
END_CASE
CASE (PLUS_TOKEN)
END_CASE
CASE (DASH_TOKEN)
Local_Float = - Parse_Float_Factor();
EXIT
END_CASE
CASE (LEFT_PAREN_TOKEN)
Local_Float = Parse_Float();
GET(RIGHT_PAREN_TOKEN);
EXIT
END_CASE
CASE (VERSION_TOKEN)
Local_Float = Language_Version;
EXIT
END_CASE
OTHERWISE
Parse_Error_Str ("float factor");
END_CASE
END_EXPECT
return (Local_Float);
}
static DBL Parse_Float_Term ()
{
DBL Local_Float;
Local_Float = Parse_Float_Factor();
EXPECT
CASE (STAR_TOKEN)
Local_Float *= Parse_Float_Factor();
END_CASE
CASE (SLASH_TOKEN)
Local_Float /= Parse_Float_Factor();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
return (Local_Float);
}
DBL Parse_Float ()
{
DBL Local_Float;
if (Language_Version < 1.5)
return(Parse_Float_Factor());
Local_Float = Parse_Float_Term();
EXPECT
CASE (PLUS_TOKEN)
Local_Float += Parse_Float_Term();
END_CASE
CASE (DASH_TOKEN)
Local_Float -= Parse_Float_Term();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
return (Local_Float);
}
static void Parse_Vector_Factor (Vector)
VECTOR *Vector;
{
EXPECT
CASE (LEFT_ANGLE_TOKEN)
Have_Vector = TRUE;
Vector -> x = Parse_Float(); Parse_Comma();
Vector -> y = Parse_Float(); Parse_Comma();
Vector -> z = Parse_Float();
GET (RIGHT_ANGLE_TOKEN);
EXIT
END_CASE
CASE (VECTOR_ID_TOKEN)
Have_Vector = TRUE;
*Vector = *((VECTOR *) Token.Constant_Data);
EXIT
END_CASE
CASE (X_TOKEN)
Have_Vector = TRUE;
Make_Vector(Vector,1.0,0.0,0.0)
EXIT
END_CASE
CASE (Y_TOKEN)
Have_Vector = TRUE;
Make_Vector(Vector,0.0,1.0,0.0)
EXIT
END_CASE
CASE (Z_TOKEN)
Have_Vector = TRUE;
Make_Vector(Vector,0.0,0.0,1.0)
EXIT
END_CASE
CASE (PLUS_TOKEN) /* uniary plus */
END_CASE
CASE (DASH_TOKEN) /* uniary minus */
Parse_Vector_Factor(Vector);
Vector -> x *= -1.0;
Vector -> y *= -1.0;
Vector -> z *= -1.0;
EXIT
END_CASE
CASE (LEFT_PAREN_TOKEN)
Parse_Vector_Float(Vector);
GET(RIGHT_PAREN_TOKEN);
EXIT
END_CASE
CASE4 (FLOAT_TOKEN, FLOAT_ID_TOKEN, CLOCK_TOKEN, VERSION_TOKEN)
UNGET
(Vector->x) =
(Vector->y) =
(Vector->z) = Parse_Float_Factor ();
EXIT
END_CASE
OTHERWISE
Parse_Error_Str ("vector factor");
END_CASE
END_EXPECT
}
static void Parse_Vector_Term (Vector)
VECTOR *Vector;
{
VECTOR Local_Vector;
Parse_Vector_Factor(Vector);
EXPECT
CASE (STAR_TOKEN)
Parse_Vector_Factor(&Local_Vector);
Vector->x *= Local_Vector.x;
Vector->y *= Local_Vector.y;
Vector->z *= Local_Vector.z;
END_CASE
CASE (SLASH_TOKEN)
Parse_Vector_Factor(&Local_Vector);
Vector->x /= Local_Vector.x;
Vector->y /= Local_Vector.y;
Vector->z /= Local_Vector.z;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
}
void Parse_Vector_Float (Vector)
VECTOR *Vector;
{
VECTOR Local_Vector;
Parse_Vector_Term(Vector);
EXPECT
CASE (PLUS_TOKEN)
Parse_Vector_Term(&Local_Vector);
Vector->x += Local_Vector.x;
Vector->y += Local_Vector.y;
Vector->z += Local_Vector.z;
END_CASE
CASE (DASH_TOKEN)
Parse_Vector_Term(&Local_Vector);
Vector->x -= Local_Vector.x;
Vector->y -= Local_Vector.y;
Vector->z -= Local_Vector.z;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
}
void Parse_Scale_Vector (Vector)
VECTOR *Vector;
{
Parse_Vector_Float(Vector);
if (Vector->x == 0.0)
{
Vector->x = 1.0;
Warn("Illegal Value: Scale X by 0.0. Changed to 1.0\n",0.0);
}
if (Vector->y == 0.0)
{
Vector->y = 1.0;
Warn("Illegal Value: Scale Y by 0.0. Changed to 1.0\n",0.0);
}
if (Vector->z == 0.0)
{
Vector->z = 1.0;
Warn("Illegal Value: Scale Z by 0.0. Changed to 1.0\n",0.0);
}
}
void Parse_Vector (Vector)
VECTOR *Vector;
{
Have_Vector = FALSE;
if (Language_Version < 1.5)
{
Parse_Vector_Factor(Vector);
}
else
{
Parse_Vector_Float (Vector);
if (!Have_Vector)
Error ("Vector expected but float only expression found");
}
}
void Parse_Colour (Colour)
COLOUR *Colour;
{
EXPECT
CASE (COLOUR_ID_TOKEN)
*Colour = *((COLOUR *) Token.Constant_Data);
EXIT
END_CASE
CASE (RGB_TOKEN)
GET (LEFT_ANGLE_TOKEN);
(Colour -> Red) = Parse_Float(); Parse_Comma();
(Colour -> Green) = Parse_Float(); Parse_Comma();
(Colour -> Blue) = Parse_Float();
(Colour -> Filter) = 0.0;
GET (RIGHT_ANGLE_TOKEN);
EXIT
END_CASE
CASE (RGBF_TOKEN)
GET (LEFT_ANGLE_TOKEN);
(Colour -> Red) = Parse_Float(); Parse_Comma();
(Colour -> Green) = Parse_Float(); Parse_Comma();
(Colour -> Blue) = Parse_Float(); Parse_Comma();
(Colour -> Filter) = Parse_Float();
GET (RIGHT_ANGLE_TOKEN);
EXIT
END_CASE
OTHERWISE
Make_Colour (Colour, 0.0, 0.0, 0.0);
UNGET
EXIT
END_CASE
END_EXPECT
EXPECT
CASE (COLOUR_ID_TOKEN)
*Colour = *((COLOUR *) Token.Constant_Data);
Warn("Previous color overwritten.",1.5);
END_CASE
CASE (RED_TOKEN)
(Colour -> Red) = Parse_Float();
END_CASE
CASE (GREEN_TOKEN)
(Colour -> Green) = Parse_Float();
END_CASE
CASE (BLUE_TOKEN)
(Colour -> Blue) = Parse_Float();
END_CASE
CASE (ALPHA_TOKEN)
Warn("Keyword ALPHA discontinued. Use FILTER instead.",1.55);
CASE (FILTER_TOKEN)
(Colour -> Filter) = Parse_Float();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
}
COLOUR_MAP *Parse_Colour_Map ()
{
COLOUR_MAP *New;
short Flag;
int i,j,c,p;
Parse_Begin ();
EXPECT
CASE (COLOUR_MAP_ID_TOKEN)
New = Copy_Colour_Map ((COLOUR_MAP *) Token.Constant_Data);
EXIT
END_CASE
OTHERWISE
UNGET
if (Build_Entries == NULL)
Build_Entries = Create_CMap_Entries(MAX_COLOUR_MAP_ENTRIES);
i = 0;
j = 1;
Flag = FALSE;
EXPECT
CASE (LEFT_SQUARE_TOKEN)
Build_Entries[i].value = Parse_Float(); Parse_Comma();
EXPECT
CASE (COLOUR_TOKEN);
Parse_Colour (&(Build_Entries[i].Colour));
Flag |= (Build_Entries[i].Colour.Filter == 0.0);
i++;
j++;
EXIT
END_CASE
OTHERWISE
UNGET
Build_Entries[j].value = Parse_Float();
GET (COLOUR_TOKEN);
Parse_Colour (&(Build_Entries[i].Colour));
Flag |= (Build_Entries[i].Colour.Filter == 0.0);
GET (COLOUR_TOKEN);
Parse_Colour (&(Build_Entries[j].Colour));
Flag |= (Build_Entries[j].Colour.Filter == 0.0);
i += 2;
j += 2;
EXIT
END_CASE
END_EXPECT
if (j > MAX_COLOUR_MAP_ENTRIES)
Error ("Colour_Map too long");
GET (RIGHT_SQUARE_TOKEN);
END_CASE
OTHERWISE
UNGET
if (i < 1)
Error ("Must have at least one color in colour map");
/* Eliminate duplicates */
for (c = 1, p = 0; c<i; c++)
{
if (memcmp(&(Build_Entries[p]),
&(Build_Entries[c]),sizeof(COLOUR_MAP_ENTRY)) == 0)
p--;
Build_Entries[++p] = Build_Entries[c];
}
p++;
New = Create_Colour_Map ();
New->Number_Of_Entries = p;
New->Colour_Map_Entries = Copy_CMap_Entries (Build_Entries,p);
New->Transparency_Flag = Flag;
EXIT
END_CASE
END_EXPECT
EXIT
END_CASE
END_EXPECT
Parse_End ();
return (New);
}
COLOUR_MAP *Parse_Colour_List (MinCount)
int MinCount;
{
COLOUR_MAP *New;
short Flag;
int i;
if (Build_Entries == NULL)
Build_Entries = Create_CMap_Entries(MAX_COLOUR_MAP_ENTRIES);
i = 0;
Flag = FALSE;
EXPECT
CASE (COLOUR_TOKEN);
Parse_Colour (&(Build_Entries[i].Colour));
Build_Entries[i].value = (DBL)i;
Flag |= (Build_Entries[i].Colour.Filter == 0.0);
i++;
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
if (i > MAX_COLOUR_MAP_ENTRIES)
Error ("Too many colors");
/* the follow code assumes MinCount of 2 or 3 */
if (i < MinCount)
{
if (MinCount == 3)
{
Make_Colour(&(Build_Entries[2].Colour),1.0,0.0,0.0);
Build_Entries[2].value = 2.0;
}
if (i < 2)
{
Make_Colour(&(Build_Entries[1].Colour),0.0,1.0,0.0);
Build_Entries[1].value = 1.0;
}
if (i == 0)
{
Make_Colour(&(Build_Entries[0].Colour),0.0,0.0,1.0);
Build_Entries[0].value = 0.0;
}
i=MinCount;
}
if (i == 0)
return (NULL);
New = Create_Colour_Map ();
New->Number_Of_Entries = i;
New->Colour_Map_Entries = Copy_CMap_Entries (Build_Entries,i);
New->Transparency_Flag = Flag;
return (New);
}